
import layout from './layouts';

// 常量
const appWidth = 1024;
const appHeight = 896;

class Painter {

	/**
	 * Sprite[]
	 */
	bgClips = [];
	/**
	 * 8 BOSS 框
	 * Sprite[]
	 */
	frames = [];
	/**
	 * 中间洛克人框
	 * Sprite
	 */
	middleFrame = null;
	/**
	 * 8 BOSS 框的底
	 * Sprite[]
	 */
	blacks = [];
	/**
	 * 中间洛克人框底
	 * Sprite
	 */
	middleBlack = null;
	/**
	 * 8 BOSS 头像
	 * Sprite[]
	 */
	avatars = [];
	/**
	 * 8 BOSS 名字
	 * Text[]
	 */
	titles = [];

	/**
	 * 上一帧记录的 this.state.anime.open 值
	 */
	prevOpen = 1;

	/**
	 * 中间洛克人头像
	 * Sprite
	 */
	middleAvatar = {
		'-1' : null,
		'0'  : null,
		'1'  : null,
		'2'  : null,
		'3'  : null,
		'4'  : null,
		'5'  : null,
		'6'  : null,
		'7'  : null,
	};

	/**
	 * 点击区域
	 * Object<number, Rectangle>
	 */
	frameZones = {
		'-1' : null,
		'0'  : null,
		'1'  : null,
		'2'  : null,
		'3'  : null,
		'4'  : null,
		'5'  : null,
		'6'  : null,
		'7'  : null,
	};

	/**
	 * 中间的光标
	 * Sprite[]
	 */
	cursors = [null, null];

	/**
	 * 参数, 光标闪啊闪啊的值.
	 * 据计算, 8 帧红灯、8 帧蓝灯, 也就是 16 帧为一个周期
	 * 
	 * 该值值域: [0, 16)
	 */
	cursorTicks = 0;

	/**
	 * 最上面的文本
	 * Text
	 */
	themeTitle = null;

	constructor (params) {
		const { PIXI, assetPath, state, ticker, events } = params;

		this.PIXI = PIXI;
		this.assetPath = assetPath;
		this.state = state;
		this.ticker = ticker;
		this.events = events;
		this.assetInfo = {};

		this.createCanvas();
	}

	createCanvas () {
		const { PIXI } = this;

		let type = "WebGL";
		if (!PIXI.utils.isWebGLSupported()) {
			type = "canvas";
		}

		let app = this.app = new PIXI.Application({width: appWidth, height: appHeight, type});
		app.stage.sortableChildren = true;
		document.getElementById("main").appendChild(app.view);

		PIXI.loader
			.add("rm3bg", this.assetPath('img/rm3bg.json'))
			.add("rm3misc", this.assetPath('img/rm3misc.json'))
			.add("rmmisc", this.assetPath('img/rmmiscsheet.json'))
			.load(() => {
				fetch(this.assetPath('img/rmmiscsheet-info.json'))
					.then((res) => res.json())
					.then((data) => { this.assetInfo = data; })
					.then(() => { this.setup(); });
			});
	}

	setup () {
		const { PIXI, app, state } = this;
		const scale = layout.bg.scale;

		// 画背景 分成三块
		for (let i = 0; i < layout.bg.clips.length; i++) {
			let bg = PIXI.Sprite.from(`rm3bg-clip${i + 1}.png`);
			bg.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;

			// let texture = PIXI.loader.resources[`rm3bg-clip${i}.png`].texture;
			// texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;
			// let bg = new PIXI.Sprite(texture);

			bg.scale.x = bg.scale.y = scale;
			bg.y = layout.bg.clips[i].y;
			bg.zIndex = 0;
			app.stage.addChild(bg);
			this.bgClips.push(bg);
		}

		// DEBUG
		global.PIXI = PIXI;
		global.app = app;

		const titleStyle = new PIXI.TextStyle({
			fontFamily: 'PressStart',
			fontSize: 32,
			fill: '#ffffff',
			fontWeight: 'bold',
			dropShadow: true,
			dropShadowColor: '#000000',
			dropShadowBlur: 0,
			dropShadowAngle: Math.PI / 4,
			dropShadowDistance: 4,
			wordWrap: true,
			wordWrapWidth: layout.titleStyle.width,
		});

		state.frames.forEach((frame, index) => {
			// 框框
			let misc = PIXI.Sprite.from('rm3-frames-normal.png');
			misc.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;

			misc.x = layout.frames[index].x;
			misc.y = layout.frames[index].y;
			misc.zIndex = layout.zIndex.frame;
			misc.scale.x = misc.scale.y = scale;

			app.stage.addChild(misc);
			this.frames.push(misc);

			// 点击区域
			this.frameZones[index] = new PIXI.Rectangle(
				layout.frames[index].x, layout.frames[index].y, 52 * scale, 48 * scale);
			
			// BOSS 黑底
			let black = PIXI.Sprite.from(`bossAvatar-null.png`);
			black.x = layout.frames[index].x + layout.framesOffset.x;
			black.y = layout.frames[index].y + layout.framesOffset.y;
			black.zIndex = layout.zIndex.black;
			black.scale.x = black.scale.y = scale;
			app.stage.addChild(black);
			this.blacks.push(black);
			
			// BOSS 图标
			let avatar = this.createAvatar(frame.avatar, index);
			avatar.zIndex = layout.zIndex.avatar;
			avatar.visible = false;

			app.stage.addChild(avatar);
			this.avatars.push(avatar);

			// 名字
			/** @type {string} */
			let name = this.handleName(frame.title);

			let textStyle = {};
			Object.assign(textStyle, titleStyle);
			let title = new PIXI.Text(name, textStyle);
			title.x = layout.title[index].x;
			title.y = layout.title[index].y;
			title.zIndex = layout.zIndex.title;
			title.visible = false;

			app.stage.addChild(title);
			this.titles.push(title);
		});

		// 中间的框框
		{
			let misc = this.middleFrame = PIXI.Sprite.from('rm3-frames-normal.png');
			misc.x = layout.middleFrame.x;
			misc.y = layout.middleFrame.y;
			misc.zIndex = layout.zIndex.frame;
			misc.scale.x = misc.scale.y = scale;
			app.stage.addChild(misc);

			// 点击区域
			this.frameZones['-1'] = new PIXI.Rectangle(
				layout.middleFrame.x, layout.middleFrame.y, 52 * scale, 48 * scale);
			
			// 黑底
			let black = this.middleBlack = PIXI.Sprite.from(`bossAvatar-null.png`);
			black.x = layout.middleFrame.x + layout.framesOffset.x;
			black.y = layout.middleFrame.y + layout.framesOffset.y;
			black.zIndex = layout.zIndex.black;
			black.scale.x = black.scale.y = scale;
			app.stage.addChild(black);
			
			// 洛克人图标
			for (let i = -1; i < 8; i++) {
				// rockAvatar-${i}.png
				let avatar = PIXI.Sprite.from(`rockAvatar-${i}.png`);
				avatar.x = layout.middleFrame.x + layout.framesOffset.x;
				avatar.y = layout.middleFrame.y + layout.framesOffset.y;
				avatar.zIndex = layout.zIndex.avatar;
				avatar.scale.x = avatar.scale.y = scale;
				avatar.visible = false;
				app.stage.addChild(avatar);

				this.middleAvatar[i] = avatar;
			}
		}

		// 光标框
		for (let i = 0; i < this.cursors.length; i++) {
			let cursor = this.cursors[i] = PIXI.Sprite.from(`rm3-frames-normalSelect${i + 1}.png`);
			cursor.visible = false;
			cursor.zIndex = layout.zIndex.cursor;
			cursor.scale.x = cursor.scale.y = scale;
			app.stage.addChild(cursor);
		}

		// 整个主题的 Title
		const themeTitleStyle = new PIXI.TextStyle({
			fontFamily: 'PressStart',
			fontSize: 32,
			fill: '#ffffff',
			fontWeight: 'bold',
			dropShadow: true,
			dropShadowColor: '#000000',
			dropShadowBlur: 0,
			dropShadowAngle: Math.PI / 4,
			dropShadowDistance: 4,
			align: 'center',
			wordWrap: true,
			wordWrapWidth: layout.themeTitle.width,
		});

		this.themeTitle = new PIXI.Text(name, themeTitleStyle);
		this.themeTitle.text = this.state.titles.normal;
		this.themeTitle.y = layout.themeTitle.y;
		this.themeTitle.zIndex = layout.zIndex.themeTitle;
		this.themeTitle.visible = false;
		this.themeTitle.x = appWidth / 2 - this.themeTitle.width / 2; // 动态计算 x
		app.stage.addChild(this.themeTitle);

		// 点击事件
		// 添加 Listener
    app.view.onclick = (event) => this.onClick(event);

		app.ticker.add((v) => this.tick(v));
	}

	onClick (event) {
		if (this.state.anime.open !== 0) {
			return;
		}

		// 框框
		for (let i = -1; i < 8; i++) {
			if (this.frameZones[i].contains(event.x, event.y)) {
				this.events.cursorMove(i);
				break;
			}
		}
	}

	tick (v) {
		this.ticker(v);

		/** @type {number} */
		const open = this.state.anime.open;
		if (open > 0) {
			// bg 位置变动
			const offset = appWidth * open;
			this.bgClips[0].x = offset;
			this.bgClips[1].x = - offset;
			this.bgClips[2].x = offset;

			this.frames.forEach((frame, index) => {
				frame.x = layout.frameAnimeDirection[index] ?
					layout.frames[index].x + offset :
					layout.frames[index].x - offset;
			});
			this.middleFrame.x = layout.middleFrameAnimeDirection ?
				layout.middleFrame.x + offset :
				layout.middleFrame.x - offset;
			this.blacks.forEach((black, index) => {
				black.x = layout.frameAnimeDirection[index] ?
					layout.frames[index].x + layout.framesOffset.x + offset :
					layout.frames[index].x + layout.framesOffset.x - offset;
			});
			this.middleBlack.x = layout.middleFrameAnimeDirection ?
				layout.middleFrame.x + layout.framesOffset.x + offset :
				layout.middleFrame.x + layout.framesOffset.x - offset;


			// 显示 -> 隐藏
			if (this.prevOpen == 0) {
				this.avatars.forEach((avatar) => {
					avatar.visible = false;
				});
				this.titles.forEach((title) => {
					title.visible = false;
				});
				this.themeTitle.visible = false;
			}

		} else {
			if (this.prevOpen > 0) {
				// 这里，入场动画结束，只调用一次
				this.bgClips[0].x = 0;
				this.bgClips[1].x = 0;
				this.bgClips[2].x = 0;
	
				this.frames.forEach((frame, index) => {
					frame.x = layout.frames[index].x;
				});
				this.middleFrame.x = layout.middleFrame.x;
				this.blacks.forEach((black, index) => {
					black.x = layout.frames[index].x + layout.framesOffset.x;
				});
				this.middleBlack.x = layout.middleFrame.x + layout.framesOffset.x;
	
				this.avatars.forEach((avatar, index) => {
					avatar.visible = this.state.frames[index].enable;
				});
				this.titles.forEach((title, index) => {
					title.visible = this.state.frames[index].enable;
				});
	
				this.cursorTicks = 0;
				this.updateThemeTitle();
				// console.log('ok');
			}

			// 确定洛克人哪个头像显示
			for (let i = -1; i < 8; i++) {
				this.middleAvatar[i].visible = (i == this.state.cursor);
			}

			// 光标
			this.cursorTicks = (this.cursorTicks + v) % 16;
			this.cursors.forEach(cursor => {
				cursor.x = this.state.cursor < 0 ?
					layout.middleFrame.x : layout.frames[this.state.cursor].x;
				cursor.y = this.state.cursor < 0 ?
					layout.middleFrame.y : layout.frames[this.state.cursor].y;
			});
			if (this.cursorTicks >= 8) {
				this.cursors[1].visible = true;
				this.cursors[0].visible = false;
			} else {
				this.cursors[0].visible = true;
				this.cursors[1].visible = false;
			}

		}


		this.prevOpen = open;
	}

	/**
	 * @param {string} name
	 * @returns {string}
	 */
	handleName (name) {
		if (name.endsWith(' MAN')) {
			let first = name.substring(0, name.length - 4);
			if (first.length <= 6) {
				return ' ' + first + '\n    MAN';
			} else if (first.length <= 8) {
				return first + '\n    MAN';
			}
			// 超出 8 个字只能默认了
		} else if (name.endsWith(' WOMAN')) {
			let first = name.substring(0, name.length - 6);
			if (first.length <= 6) {
				return ' ' + first + '\n  WOMAN';
			} else if (first.length <= 8) {
				return first + '\n  WOMAN';
			}
			// 超出 8 个字只能默认了
		}

		// 默认情况，即不是 AAA MAN / AAA WOMAN 的文本
		if (name.length <= 7) {
			return ' ' + name;
		} else if (name.length === 8) {
			return name;
		} else {
			let index = name.indexOf(' ', 4);
			/** @type {string} 第一行文本 */
			let first;
			/** @type {string} 第二行文本 */
			let second;
			/** @type {string} 换行文本 */
			let split;

			if (index < 0 || index > 7) {
				first = name.substring(0, 8);
				second = name.substring(8).trim();
			} else {
				first = ' ' + name.substring(0, index);
				second = name.substring(index + 1).trim();
			}

			if (second.length <= 7) {
				split = '\n ';
			} else {
				split = '\n';
			}
			return first + split + second;
		}
	}

	/**
	 * Boss avatar / Title 发生修改
	 */
	updateFrames (dirtMap) {
		const { PIXI, state } = this;

		// enable
		if (state.anime.open === 0) {
			dirtMap.forEach((dirts, index) => {
				if (dirts.enable) {
					this.avatars[index].visible = state.frames[index].enable;
					this.titles[index].visible = state.frames[index].enable;
				}
			});
		}

		// title
		dirtMap.forEach((dirts, index) => {
			if (dirts.title) {
				this.titles[index].text = this.handleName(state.frames[index].title);
			}
		});

		// avatar
		dirtMap.forEach((dirts, index) => {
			if (dirts.avatar) {
				let frame = state.frames[index];
				let avatar = this.createAvatar(frame.avatar, index);
				avatar.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;

				avatar.zIndex = layout.zIndex.avatar;
				avatar.visible = state.frames[index].enable && this.avatars[index].visible;

				app.stage.removeChild(this.avatars[index]);
				app.stage.addChild(avatar);
				this.avatars[index] = avatar;
			}
		});
	}

	/**
	 * 当 state.anime 状态发生变化
	 * 包括： open 变为 2 / 1
	 */
	updateAnime () {
		if (this.state.anime.open > 0) {
			// 中间的洛克人头
			Object.values(this.middleAvatar).forEach(avatar => {
				avatar.visible = false;
			});
			Object.values(this.cursors).forEach(avatar => {
				avatar.visible = false;
			});
			this.themeTitle.visible = false;
		}
	}

	/**
	 * 创建 avatar
	 * @param {string} avatarName 
	 * @param {number} index 
	 */
	createAvatar (avatarName, index) {
		const { PIXI } = this;
		let name = `bossAvatar-${avatarName}.png`;
		const avatar = PIXI.Sprite.from(name);

		let x = layout.frames[index].x + layout.framesOffset.x;
		let y = layout.frames[index].y + layout.framesOffset.y;
		let scale = layout.bg.scale;

		if (this.assetInfo[name]) {
			let info = this.assetInfo[name];
			if (info.scale != undefined) {
				scale *= info.scale;
			}
			if (info.offsetX != undefined) {
				x -= (info.offsetX * scale);
			}
			if (info.offsetY != undefined) {
				y -= (info.offsetY * scale);
			}
		}

		avatar.x = x;
		avatar.y = y;
		avatar.scale.x = avatar.scale.y = scale;

		return avatar;
	}

	onRoundStart () {
		this.updateThemeTitle();
	}

	onRoundEnd () {
		this.updateThemeTitle();
	}

	updateThemeTitle () {
		const { anime, titles, round } = this.state;
		const { themeTitle } = this;

		if (anime.open > 0 || anime.selected > 0) {
			themeTitle.visible = false;
			return;
		} else if (round) {
			// 正在抽奖
			themeTitle.text = titles.round;
			themeTitle.visible = true;
			themeTitle.x = appWidth / 2 - this.themeTitle.width / 2; // 动态计算 x
		} else {
			// 没在抽奖
			themeTitle.text = titles.normal;
			themeTitle.visible = true;
			themeTitle.x = appWidth / 2 - this.themeTitle.width / 2; // 动态计算 x
		}
	}
	
}

export default Painter;
